﻿using System.Runtime.CompilerServices;

namespace KinonekoSoftware.Foundation.UI.Drawings
{
    /// <summary>
    /// 椭圆方程的计算
    /// </summary>
    public class EllipticEquation
    {
        public const double ArcSegment_MaxAngle = 359d;
        
        /// <summary>
        /// 获得弧线段的参数
        /// </summary>
        /// <param name="angle">角度</param>
        /// <param name="radius">半径（需要处理过）</param>
        /// <param name="endPointX"></param>
        /// <param name="endPointY"></param>
        /// <remarks>
        /// 注意，radius 需要提前处理过轮廓的影响。
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void GetArcSegments(
            double angle,
            double radius,
            out double endPointX, 
            out double endPointY)
        {
            var radian = CircularEquation.Angle2Radian(angle);
            var a      = radius * Math.Sin(radian);
            var b      = radian * Math.Cos(radian);
            endPointX = radius + a;
            endPointY = radius - b;
        }
        
        /// <summary>
        /// 获得弧线段的参数
        /// </summary>
        /// <param name="angle">角度</param>
        /// <param name="radius">半径（需要处理过）</param>
        /// <param name="isLarge">输出，是否是大弧线</param>
        /// <param name="isClose">输出，是否为闭合曲线</param>
        /// <param name="endPointX">输出，弧线末端X坐标</param>
        /// <param name="endPointY">输出，弧线末端Y坐标</param>
        /// <remarks>
        /// 注意，radius 需要提前处理过轮廓的影响。
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void GetArcSegments(
            double angle,
            double radius, 
            out bool isLarge, 
            out bool isClose, 
            out double endPointX, 
            out double endPointY)
        {
            angle = Math.Min(angle, ArcSegment_MaxAngle);
            var radian = CircularEquation.Angle2Radian(angle);
            var a      = radius * Math.Sin(radian);
            var b      = radius * Math.Cos(radian);
            isLarge   = angle >= 180;
            isClose   = angle >= ArcSegment_MaxAngle;
            endPointX = radius + a;
            endPointY = radius - b;
        }

        /// <summary>
        /// 获得指定控件的直径数据
        /// </summary>
        /// <param name="actualWidth">真实的宽度</param>
        /// <param name="actualHeight">真实的高度</param>
        /// <returns>返回一个 <see cref="DiameterResult"/> 实例。</returns>
        public static DiameterResult ComputeDiameter(double actualWidth, double actualHeight)
        {
            var r = false;
            if (double.IsInfinity(actualHeight))
            {
                r            = true;
                actualHeight = 0;
            }
            
            
            if (double.IsInfinity(actualWidth))
            {
                r           = true;
                actualWidth = 0;
            }
            
            var diameter = Math.Min(actualWidth, actualHeight);
            var radius   = diameter / 2d;

            return new DiameterResult
            {
                IsZero      = r,
                OriginValue = diameter,
                Value       = diameter,
                CenterX     = radius,
                CenterY     = radius,
            };
        }
    }
}